home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / GCC / V2-4-5 / GPPLIBSR00 / cc / iostream < prev    next >
Text File  |  1993-12-07  |  17KB  |  774 lines

  1. //    This is part of the iostream library, providing input/output for C++.
  2. //    Copyright (C) 1991, 1992 Per Bothner.
  3. //
  4. //    This library is free software; you can redistribute it and/or
  5. //    modify it under the terms of the GNU Library General Public
  6. //    License as published by the Free Software Foundation; either
  7. //    version 2 of the License, or (at your option) any later version.
  8. //
  9. //    This library is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. //    Library General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU Library General Public
  15. //    License along with this library; if not, write to the Free
  16. //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19. #ifdef __GNUG__
  20. #pragma implementation "iostream.h"
  21. #endif
  22. #define _STREAM_COMPAT
  23. #include "ioprivate.h"
  24. #include <iostream.h>
  25.  
  26. extern "C"
  27.   {
  28.   #include <stdio.h>  /* Needed for sprintf */
  29.   #include <ctype.h>
  30.   #include <limits.h>
  31.   }
  32.  
  33. #include "floatio.h"
  34.  
  35. #define RISCOS
  36.  
  37.  
  38. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  39.  
  40. //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
  41.  
  42. istream::istream(streambuf *sb, ostream* tied) : ios(sb, tied)
  43. {
  44.     _flags |= ios::dont_close;
  45.     _gcount = 0;
  46. }
  47.  
  48. int skip_ws(streambuf* sb)
  49. {
  50.     int ch;
  51.     for (;;) {
  52.     ch = sb->sbumpc();
  53.     if (ch == EOF || !isspace(ch))
  54.         return ch;
  55.     }
  56. }
  57.  
  58. istream& istream::get(char& c)
  59. {
  60.     if (ipfx1()) {
  61.     int ch = _strbuf->sbumpc();
  62.     if (ch == EOF) set(ios::eofbit|ios::failbit);
  63.     else c = (char)ch;
  64.     }
  65.     return *this;
  66. }
  67.  
  68. istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */)
  69. {
  70.     if (ipfx1()) {
  71.     register streambuf* sb = _strbuf;
  72.     if (delim == EOF) {
  73.         _gcount = sb->ignore(n);
  74.         return *this;
  75.     }
  76.     _gcount = 0;
  77.     for (;;) {
  78. #if 0
  79.         if (n != MAXINT) // FIXME
  80. #endif
  81.         if (--n < 0)
  82.         break;
  83.         int ch = sb->sbumpc();
  84.         if (ch == EOF) {
  85.         set(ios::eofbit|ios::failbit);
  86.         break;
  87.         }
  88.         _gcount++;
  89.         if (ch == delim)
  90.         break;
  91.     }
  92.     }
  93.     return *this;
  94. }
  95.  
  96. istream& istream::read(char *s, int n)
  97. {
  98.     if (ipfx1()) {
  99.     _gcount = _strbuf->sgetn(s, n);
  100.     if (_gcount != n)
  101.         set(ios::failbit);
  102.     }
  103.     return *this;
  104. }
  105.  
  106. istream& istream::seekg(streampos pos)
  107. {
  108.     pos = _strbuf->seekpos(pos, ios::in);
  109.     if (pos == streampos(EOF))
  110.     set(ios::badbit);
  111.     return *this;
  112. }
  113.  
  114. istream& istream::seekg(streamoff off, _seek_dir dir)
  115. {
  116.     streampos pos = _strbuf->seekoff(off, dir, ios::in);
  117.     if (pos == streampos(EOF))
  118.     set(ios::badbit);
  119.     return *this;
  120. }
  121.  
  122. streampos istream::tellg()
  123. {
  124.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::in);
  125.     if (pos == streampos(EOF))
  126.     set(ios::badbit);
  127.     return pos;
  128. }
  129.  
  130. istream& istream::scan(const char *format ...)
  131. {
  132.     if (ipfx0()) {
  133.     va_list ap;
  134.     va_start(ap, format);
  135.     _strbuf->vscan(format, ap, this);
  136.     va_end(ap);
  137.     }
  138.     return *this;
  139. }
  140.  
  141. istream& istream::vscan(const char *format, _G_va_list args)
  142. {
  143.     if (ipfx0())
  144.     _strbuf->vscan(format, args, this);
  145.     return *this;
  146. }
  147.  
  148. istream& istream::operator>>(char& c)
  149. {
  150.     if (ipfx0()) {
  151.     int ch = _strbuf->sbumpc();
  152.     if (ch == EOF)
  153.         set(ios::eofbit|ios::failbit);
  154.     else
  155.         c = (char)ch;
  156.     }
  157.     return *this;
  158. }
  159.  
  160. istream& istream::operator>>(char* ptr)
  161. {
  162.     if (ipfx0()) {
  163.     register streambuf* sb = _strbuf;
  164.     int ch = sb->sbumpc();
  165.     if (ch == EOF)
  166.         set(ios::eofbit|ios::failbit);
  167.     else {
  168.         int w = width(0);
  169.         *ptr++ = ch;
  170.         for (;;) {
  171.         ch = sb->sbumpc();
  172.         if (ch == EOF) {
  173.             set(ios::eofbit|ios::failbit);
  174.             break;
  175.         }
  176.         else if (isspace(ch)) {
  177.             sb->sputbackc(ch);
  178.             break;
  179.         }
  180.         else if (w == 1) {
  181.             set(ios::failbit);
  182.             sb->sputbackc(ch);
  183.             break;
  184.         }
  185.         else *ptr++ = ch;
  186.         w--;
  187.         }
  188.     }
  189.     }
  190.     *ptr = '\0';
  191.     return *this;
  192. }
  193.  
  194. #ifndef RISCOS
  195. #ifdef __GNUC__
  196. #define LONGEST long long
  197. #else
  198. #define LONGEST long
  199. #endif
  200. #else
  201. #define LONGEST long
  202. #endif
  203.  
  204. static int read_int(istream& stream, unsigned LONGEST& val, int& neg)
  205. {
  206.     if (!stream.ipfx0())
  207.     return 0;
  208.     register streambuf* sb = stream.rdbuf();
  209.     int base = 10;
  210.     int ndigits = 0;
  211.     register int ch = skip_ws(sb);
  212.     if (ch == EOF)
  213.     goto eof_fail;
  214.     neg = 0;
  215.     if (ch == '+') {
  216.     ch = skip_ws(sb);
  217.     }
  218.     else if (ch == '-') {
  219.     neg = 1;
  220.     ch = skip_ws(sb);
  221.     }
  222.     if (ch == EOF) goto eof_fail;
  223.     if (!(stream.flags() & ios::basefield)) {
  224.     if (ch == '0') {
  225.         ch = sb->sbumpc();
  226.         if (ch == EOF) {
  227.         val = 0;
  228.         return 1;
  229.         }
  230.         if (ch == 'x' || ch == 'X') {
  231.         base = 16;
  232.         ch = sb->sbumpc();
  233.         if (ch == EOF) goto eof_fail;
  234.         }
  235.         else {
  236.         sb->sputbackc(ch);
  237.         base = 8;
  238.         ch = '0';
  239.         }
  240.     }
  241.     }
  242.     else if ((stream.flags() & ios::basefield) == ios::hex)
  243.     base = 16;
  244.     else if ((stream.flags() & ios::basefield) == ios::oct)
  245.     base = 8;
  246.     val = 0;
  247.     for (;;) {
  248.     if (ch == EOF)
  249.         break;
  250.     int digit;
  251.     if (ch >= '0' && ch <= '9')
  252.         digit = ch - '0';
  253.     else if (ch >= 'A' && ch <= 'F')
  254.         digit = ch - 'A' + 10;
  255.     else if (ch >= 'a' && ch <= 'f')
  256.         digit = ch - 'a' + 10;
  257.     else
  258.         digit = 999;
  259.     if (digit >= base) {
  260.         sb->sputbackc(ch);
  261.         if (ndigits == 0)
  262.         goto fail;
  263.         else
  264.         return 1;
  265.     }
  266.     ndigits++;
  267.     val = base * val + digit;
  268.     ch = sb->sbumpc();
  269.     }
  270.     return 1;
  271.   fail:
  272.     stream.set(ios::failbit);
  273.     return 0;
  274.   eof_fail:
  275.     stream.set(ios::failbit|ios::eofbit);
  276.     return 0;
  277. }
  278.  
  279. #define READ_INT(TYPE) \
  280. istream& istream::operator>>(TYPE& i)\
  281. {\
  282.     unsigned LONGEST val; int neg;\
  283.     if (read_int(*this, val, neg)) {\
  284.     if (neg) val = -val;\
  285.     i = (TYPE)val;\
  286.     }\
  287.     return *this;\
  288. }
  289.  
  290. READ_INT(short)
  291. READ_INT(unsigned short)
  292. READ_INT(int)
  293. READ_INT(unsigned int)
  294. READ_INT(long)
  295. READ_INT(unsigned long)
  296. //#ifdef __GNUG__
  297. //READ_INT(long long)
  298. //READ_INT(unsigned long long)
  299. //#endif
  300.  
  301. istream& istream::operator>>(double& x)
  302. {
  303.     if (ipfx0())
  304.     scan("%lg", &x);
  305.     return *this;
  306. }
  307.  
  308. istream& istream::operator>>(float& x)
  309. {
  310.     if (ipfx0())
  311.     scan("%g", &x);
  312.     return *this;
  313. }
  314.  
  315. istream& istream::operator>>(register streambuf* sbuf)
  316. {
  317.     if (ipfx0()) {
  318.     register streambuf* inbuf = rdbuf();
  319.     // FIXME: Should optimize!
  320.     for (;;) {
  321.         register int ch = inbuf->sbumpc();
  322.         if (ch == EOF) {
  323.         set(ios::eofbit);
  324.         break;
  325.         }
  326.         if (sbuf->sputc(ch) == EOF) {
  327.         set(ios::failbit);
  328.         break;
  329.         }
  330.     }
  331.     }
  332.     return *this;
  333. }
  334.  
  335. ostream& ostream::operator<<(char c)
  336. {
  337.     if (opfx()) {
  338.     int w = width(0);
  339.     char fill_char = fill();
  340.     register int padding = w > 0 ? w - 1 : 0;
  341.     register streambuf *sb = _strbuf;
  342.     if (!(flags() & ios::left)) // Default adjustment.
  343.         while (--padding >= 0) sb->sputc(fill_char);
  344.     sb->sputc(c);
  345.     if (flags() & ios::left) // Left adjustment.
  346.         while (--padding >= 0) sb->sputc(fill_char);
  347.     osfx();
  348.     }
  349.     return *this;
  350. }
  351.  
  352. static void write_int(ostream& stream, unsigned LONGEST val, int neg)
  353. {
  354. #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
  355.     char buf[WRITE_BUF_SIZE];
  356.     register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf.
  357.     char *show_base = "";
  358.     int show_base_len = 0;
  359.  
  360.     // Now do the actual conversion, placing the result at the *end* of buf.
  361.     // Note that we use separate code for decimal, octal, and hex,
  362.     // so we can divide by optimizable constants.
  363.     if ((stream.flags() & ios::basefield) == ios::oct) { // Octal
  364.     if ((stream.flags() & ios::showbase) && (val != 0))
  365.         show_base = "0", show_base_len = 1;
  366.     do {
  367.         *--buf_ptr = (val & 7) + '0';
  368.         val = val >> 3;
  369.     } while (val != 0);
  370.     }
  371.     else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex
  372.     char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X"
  373.         : "0123456789abcdef0x";
  374.     do {
  375.         *--buf_ptr = xdigs[val & 15];
  376.         val = val >> 4;
  377.     } while (val != 0);
  378.     if (stream.flags() & ios::showbase) {
  379.         show_base = xdigs + 16; // Either "0X" or "0x".
  380.         show_base_len = 2;
  381.     }
  382.     }
  383.     else { // Decimal
  384. #ifndef RISCOS
  385. #ifdef __GNUC__
  386.     // Optimization:  Only use long long when we need to.
  387.     while (val > UINT_MAX) {
  388.         *--buf_ptr = (val % 10) + '0';
  389.         val /= 10;
  390.     }
  391.     // Use more efficient (int) arithmetic for the rest.
  392.     register unsigned int ival = (unsigned int)val;
  393. #else
  394.     register unsigned LONGEST ival = val;
  395. #endif
  396. #else
  397.     register unsigned LONGEST ival = val;
  398. #endif
  399.     do {
  400.         *--buf_ptr = (ival % 10) + '0';
  401.         ival /= 10;
  402.     } while (ival != 0);
  403.     }
  404.  
  405.     int buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
  406.     int w = stream.width(0);
  407.     int show_pos = 0;
  408.  
  409.     // Calculate padding.
  410.     int len = buf_len;
  411.     if (neg) len++;
  412.     else if (val != 0 && (stream.flags() & ios::showpos)) len++, show_pos=1;
  413.     len += show_base_len;
  414.     int padding = len > w ? 0 : w - len;
  415.  
  416.     // Do actual output.
  417.     register streambuf* sbuf = stream.rdbuf();
  418.     ios::fmtflags pad_kind =
  419.     stream.flags() & (ios::left|ios::right|ios::internal);
  420.     char fill_char = stream.fill();
  421.     if (padding > 0
  422.     && pad_kind != (ios::fmtflags)ios::left
  423.     && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
  424.     sbuf->padn(fill_char, padding);
  425.     if (neg) sbuf->sputc('-');
  426.     else if (show_pos) sbuf->sputc('+');
  427.     if (show_base_len)
  428.     sbuf->sputn(show_base, show_base_len);
  429.     if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
  430.     sbuf->padn(fill_char, padding);
  431.     sbuf->sputn(buf_ptr, buf_len);
  432.     if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
  433.     sbuf->padn(fill_char, padding);
  434.     stream.osfx();
  435. }
  436.  
  437. ostream& ostream::operator<<(int n)
  438. {
  439.     if (opfx()) {
  440.     int neg = 0;
  441.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  442.         n = -n, neg = 1;
  443.     write_int(*this, n, neg);
  444.     }
  445.     return *this;
  446. }
  447.  
  448. ostream& ostream::operator<<(unsigned int n)
  449. {
  450.     if (opfx())
  451.     write_int(*this, n, 0);
  452.     return *this;
  453. }
  454.  
  455.  
  456. ostream& ostream::operator<<(long n)
  457. {
  458.     if (opfx()) {
  459.     int neg = 0;
  460.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  461.         n = -n, neg = 1;
  462.     write_int(*this, n, neg);
  463.     }
  464.     return *this;
  465. }
  466.  
  467. ostream& ostream::operator<<(unsigned long n)
  468. {
  469.     if (opfx())
  470.     write_int(*this, n, 0);
  471.     return *this;
  472. }
  473.  
  474. #ifndef RISCOS
  475. #ifdef __GNUG__
  476. ostream& ostream::operator<<(long long n)
  477. {
  478.     if (opfx()) {
  479.     int neg = 0;
  480.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  481.         n = -n, neg = 1;
  482.     write_int(*this, n, neg);
  483.     }
  484.     return *this;
  485. }
  486.  
  487.  
  488. ostream& ostream::operator<<(unsigned long long n)
  489. {
  490.     if (opfx())
  491.     write_int(*this, n, 0);
  492.     return *this;
  493. }
  494. #endif /*__GNUG__*/
  495. #endif /* RISCOS */
  496.  
  497. ostream& ostream::operator<<(double n)
  498. {
  499.     if (opfx()) {
  500.     // Uses __cvt_double (renamed from static cvt), in Chris Torek's
  501.     // stdio implementation.  The setup code uses the same logic
  502.     // as in __vsbprintf.C (also based on Torek's code).
  503.     int format_char;
  504. #if 0
  505.     if (flags() ios::showpos) sign = '+';
  506. #endif
  507.     if ((flags() & ios::floatfield) == ios::fixed)
  508.         format_char = 'f';
  509.     else if ((flags() & ios::floatfield) == ios::scientific)
  510.         format_char = flags() & ios::uppercase ? 'E' : 'e';
  511.     else
  512.         format_char = flags() & ios::uppercase ? 'G' : 'g';
  513.  
  514.     int fpprec = 0; // 'Extra' (suppressed) floating precision.
  515.     int prec = precision();
  516.     if (prec < 0) prec = 6; // default.
  517.     else if (prec > MAXFRACT) {
  518.         if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
  519.         fpprec = prec - MAXFRACT;
  520.         prec = MAXFRACT;
  521.     }
  522.  
  523.     // Do actual conversion.
  524. #ifdef USE_DTOA
  525.     if (__outfloat(n, rdbuf(), format_char, width(0),
  526.                precision(), flags(), 0, fill()) < 0)
  527.         set(ios::badbit|ios::failbit); // ??
  528. #else
  529.     int negative;
  530.     char buf[BUF];
  531.     int sign = '\0';
  532.     char *cp = buf;
  533.     *cp = 0;
  534.     int size = __cvt_double(n, precision(),
  535.                 flags() & ios::showpoint ? 0x80 : 0,
  536.                 &negative,
  537.                 format_char, cp, buf + sizeof(buf));
  538.     if (negative) sign = '-';
  539.     if (*cp == 0)
  540.         cp++;
  541.  
  542.     // Calculate padding.
  543.     int fieldsize = size + fpprec;
  544.     if (sign) fieldsize++;
  545.     int padding = 0;
  546.     int w = width(0);
  547.     if (fieldsize < w)
  548.         padding = w - fieldsize;
  549.  
  550.     // Do actual output.
  551.     register streambuf* sbuf = rdbuf();
  552.     register i;
  553.     char fill_char = fill();
  554.     ios::fmtflags pad_kind =
  555.         flags() & (ios::left|ios::right|ios::internal);
  556.     if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust.
  557.         && pad_kind != (ios::fmtflags)ios::internal)
  558.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  559.     if (sign)
  560.         sbuf->sputc(sign);
  561.     if (pad_kind == (ios::fmtflags)ios::internal)
  562.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  563.     
  564.     // Emit the actual concented field, followed by extra zeros.
  565.     sbuf->sputn(cp, size);
  566.     for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
  567.  
  568.     if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment
  569.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  570. #endif
  571.     osfx();
  572.     }
  573.     return *this;
  574. }
  575.  
  576. ostream& ostream::operator<<(const char *s)
  577. {
  578.     if (opfx()) {
  579.     if (s == NULL)
  580.         s = "(null)";
  581.     int len = strlen(s);
  582.     int w = width(0);
  583.     char fill_char = fill();
  584.     register streambuf *sbuf = rdbuf();
  585.     register int padding = w > len ? w - len : 0;
  586.     if (!(flags() & ios::left)) // Default adjustment.
  587.         while (--padding >= 0) sbuf->sputc(fill_char);
  588.     sbuf->sputn(s, len);
  589.     if (flags() & ios::left) // Left adjustment.
  590.         while (--padding >= 0) sbuf->sputc(fill_char);
  591.     osfx();
  592.     }
  593.     return *this;
  594. }
  595.  
  596. ostream& ostream::operator<<(void *p)
  597. {
  598.     if (opfx()) {
  599.     form("%p", p);
  600.     osfx();
  601.     }
  602.     return *this;
  603. }
  604.  
  605. ostream& ostream::operator<<(register streambuf* sbuf)
  606. {
  607.     if (opfx()) {
  608.     register streambuf* outbuf = rdbuf();
  609.     // FIXME: Should optimize!
  610.     for (;;) {
  611.         register int ch = sbuf->sbumpc();
  612.         if (ch == EOF) break;
  613.         if (outbuf->sputc(ch) == EOF) {
  614.         set(ios::badbit);
  615.         break;
  616.         }
  617.     }
  618.     osfx();
  619.     }
  620.     return *this;
  621. }
  622.  
  623. ostream::ostream(streambuf* sb, ostream* tied) : ios(sb, tied)
  624. {
  625.     _flags |= ios::dont_close;
  626. }
  627.  
  628. ostream& ostream::seekp(streampos pos)
  629. {
  630.     pos = _strbuf->seekpos(pos, ios::out);
  631.     if (pos == streampos(EOF))
  632.     set(ios::badbit);
  633.     return *this;
  634. }
  635.  
  636. ostream& ostream::seekp(streamoff off, _seek_dir dir)
  637. {
  638.     streampos pos = _strbuf->seekoff(off, dir, ios::out);
  639.     if (pos == streampos(EOF))
  640.     set(ios::badbit);
  641.     return *this;
  642. }
  643.  
  644. streampos ostream::tellp()
  645. {
  646.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::out);
  647.     if (pos == streampos(EOF))
  648.     set(ios::badbit);
  649.     return pos;
  650. }
  651.  
  652. ostream& ostream::form(const char *format ...)
  653. {
  654.     if (opfx()) {
  655.     va_list ap;
  656.     va_start(ap, format);
  657.     _strbuf->vform(format, ap);
  658.     va_end(ap);
  659.     }
  660.     return *this;
  661. }
  662.  
  663. ostream& ostream::vform(const char *format, _G_va_list args)
  664. {
  665.     if (opfx())
  666.     _strbuf->vform(format, args);
  667.     return *this;
  668. }
  669.  
  670. ostream& ostream::flush()
  671. {
  672.     if (_strbuf->sync())
  673.     set(ios::badbit);
  674.     return *this;
  675. }
  676.  
  677. ostream& flush(ostream& outs)
  678. {
  679.     outs.rdbuf()->overflow(EOF);
  680.     return outs;
  681. }
  682.  
  683. istream& ws(istream& ins)
  684. {
  685.     if (ins.ipfx1()) {
  686.     int ch = skip_ws(ins._strbuf);
  687.     if (ch == EOF)
  688.         ins.set(ios::eofbit);
  689.     else
  690.         ins._strbuf->sputbackc(ch);
  691.     }
  692.     return ins;
  693. }
  694.  
  695. // Skip white-space.  Return 0 on failure (EOF), or 1 on success.
  696. // Differs from ws() manipulator in that failbit is set on EOF.
  697. // Called by ipfx() and ipfx0() if needed.
  698.  
  699. int istream::_skip_ws()
  700. {
  701.     int ch = skip_ws(_strbuf);
  702.     if (ch == EOF) {
  703.     set(ios::eofbit|ios::failbit);
  704.     return 0;
  705.     }
  706.     else {
  707.     _strbuf->sputbackc(ch);
  708.     return 1;
  709.     }
  710. }
  711.  
  712. ostream& ends(ostream& outs)
  713. {
  714.     outs.put(0);
  715.     return outs;
  716. }
  717.  
  718. ostream& endl(ostream& outs)
  719. {
  720.     return flush(outs.put('\n'));
  721. }
  722.  
  723. ostream& ostream::write(const char *s, int n)
  724. {
  725.     if (opfx()) {
  726.     if (_strbuf->sputn(s, n) != n)
  727.         set(ios::failbit);
  728.     }
  729.     return *this;
  730. }
  731.  
  732. void ostream::do_osfx()
  733. {
  734.     if (flags() & ios::unitbuf)
  735.     flush();
  736.     if (flags() & ios::stdio) {
  737.     fflush(stdout);
  738.     fflush(stderr);
  739.     }
  740. }
  741.  
  742. iostream::iostream(streambuf* sb, ostream* tied) : ios(sb, tied)
  743. {
  744.     _flags |= ios::dont_close;
  745.     _gcount = 0;
  746. }
  747.  
  748. // NOTE: extension for compatibility with old libg++.
  749. // Not really compatible with fistream::close().
  750. #ifdef _STREAM_COMPAT
  751. void ios::close()
  752. {
  753.     if (!(_flags & (unsigned int)ios::dont_close))
  754.     delete _strbuf;
  755.     else if (_strbuf->_flags & _S_IS_FILEBUF)
  756.     ((struct filebuf*)_strbuf)->close();
  757.     else if (_strbuf != NULL)
  758.     _strbuf->sync();
  759.     _flags |= ios::dont_close;
  760.     _strbuf = NULL;
  761.     _state = badbit;
  762. }
  763.  
  764. int istream::skip(int i)
  765. {
  766.     int old = (_flags & ios::skipws) != 0;
  767.     if (i)
  768.     _flags |= ios::skipws;
  769.     else
  770.     _flags &= ~ios::skipws;
  771.     return old;
  772. }
  773. #endif
  774.